package com.pai4j.user.service.group;

import com.pai4j.common.util.JsonUtil;
import com.pai4j.domain.vo.request.group.CreateOrUpdateGroupRequestVO;
import com.pai4j.domain.vo.request.group.UpdateGroupMemberSettingRequestVO;
import com.pai4j.domain.vo.response.group.GroupInfoResponseVO;
import com.pai4j.user.repository.dao.IGroupInfoDAO;
import com.pai4j.user.repository.dao.IGroupMemberSettingDAO;
import com.pai4j.user.repository.entity.GroupInfoEntity;
import com.pai4j.user.repository.entity.GroupMemberSettingEntity;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Service
public class GroupService {

    @Resource
    private IGroupInfoDAO groupInfoDAO;
    @Resource
    private IGroupMemberSettingDAO groupMemberSettingDAO;
    /**
     * 创建或更新群组信息。
     * 如果请求中包含有效的 paiId，则尝试查找已存在的群组；否则生成新的 paiId。
     * 群组的基本信息（如名称、公告、头像等）将根据请求内容进行设置。
     *
     * @param req 包含群组创建或更新信息的请求对象，不能为空
     * @return 返回包含最新群组信息的响应对象
     */
    public GroupInfoResponseVO createOrUpdate(CreateOrUpdateGroupRequestVO req) {
        GroupInfoEntity entity = null;
        Date now = new Date();
        // 根据 paiId 查找现有群组
        if (StringUtils.isNotBlank(req.getPaiId())) {
            entity = groupInfoDAO.findByPaiId(req.getPaiId());
        }
        // 若未找到现有群组，则新建一个
        if (entity == null) {
            entity = new GroupInfoEntity();
            entity.setPaiId(StringUtils.isNotBlank(req.getPaiId()) ? req.getPaiId() : genPaiId());
            entity.setCreateDate(now);
        }
        // 设置群组基本信息
        entity.setName(req.getName());
        entity.setAnnouncement(req.getAnnouncement());
        entity.setRemark(req.getRemark());
        entity.setAvatar(req.getAvatar());
        entity.setOwnerId(req.getOwnerId());
        entity.setJoinMode(req.getJoinMode() == null ? 0 : req.getJoinMode());
        entity.setMaxMembers(req.getMaxMembers() == null ? 500 : req.getMaxMembers());
        entity.setStatus(req.getStatus() == null ? 1 : req.getStatus());
        entity.setExt(map2json(req.getExt()));
        entity.setUpdateDate(now);
        entity = groupInfoDAO.save(entity);
        return toVO(entity);
    }

    /**
     * 根据 paiId 获取群组信息。
     *
     * @param paiId 群组唯一标识符，不能为空
     * @return 返回对应的群组信息响应对象，若未找到则返回 null
     */
    public GroupInfoResponseVO get(String paiId) {
        GroupInfoEntity entity = groupInfoDAO.findByPaiId(paiId);
        if (entity == null) {
            return null;
        }
        return toVO(entity);
    }

    /**
     * 更新指定用户在指定群组中的成员设置。
     * 如果该用户的设置不存在，则创建一个新的设置记录。
     *
     * @param req 包含群组成员设置更新信息的请求对象，不能为空
     * @return 操作成功返回 true
     */
    public boolean updateMemberSetting(UpdateGroupMemberSettingRequestVO req) {
        GroupMemberSettingEntity setting = groupMemberSettingDAO.findByGroupPaiIdAndUserAccount(req.getGroupPaiId(), req.getUserAccount());
        Date now = new Date();
        // 如果设置不存在，则新建
        if (setting == null) {
            setting = new GroupMemberSettingEntity();
            setting.setGroupPaiId(req.getGroupPaiId());
            setting.setUserAccount(req.getUserAccount());
            setting.setCreateDate(now);
        }
        // 更新非空字段
        if (req.getMute() != null) setting.setMute(req.getMute());
        if (req.getPinned() != null) setting.setPinned(req.getPinned());
        if (req.getDisplayNickname() != null) setting.setDisplayNickname(req.getDisplayNickname());
        if (req.getChatBackground() != null) setting.setChatBackground(req.getChatBackground());
        if (req.getExt() != null) setting.setExt(map2json(req.getExt()));
        setting.setUpdateDate(now);
        groupMemberSettingDAO.save(setting);
        return true;
    }

    /**
     * 获取指定用户在指定群组中的成员设置。
     *
     * @param groupPaiId 群组唯一标识符
     * @param userAccount 用户账号
     * @return 返回包含成员设置信息的请求对象，若未找到则返回 null
     */
    public UpdateGroupMemberSettingRequestVO getMemberSetting(String groupPaiId, String userAccount) {
        GroupMemberSettingEntity setting = groupMemberSettingDAO.findByGroupPaiIdAndUserAccount(groupPaiId, userAccount);
        if (setting == null) return null;
        UpdateGroupMemberSettingRequestVO vo = new UpdateGroupMemberSettingRequestVO();
        vo.setGroupPaiId(setting.getGroupPaiId());
        vo.setUserAccount(setting.getUserAccount());
        vo.setMute(setting.getMute());
        vo.setPinned(setting.getPinned());
        vo.setDisplayNickname(setting.getDisplayNickname());
        vo.setChatBackground(setting.getChatBackground());
        vo.setExt(json2map(setting.getExt()));
        return vo;
    }

    /**
     * 生成一个新的群组唯一标识符（paiId），格式为 "G" + UUID（去除横线）。
     *
     * @return 新生成的 paiId 字符串
     */
    private String genPaiId() {
        return "G" + UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 将 Map 转换为 JSON 字符串。
     *
     * @param map 待转换的 Map 对象
     * @return 转换后的 JSON 字符串，若 map 为 null 则返回 null
     */
    private String map2json(Map<String, Object> map) {
        return map == null ? null : JsonUtil.toJsonString(map);
    }

    /**
     * 将 JSON 字符串解析为 Map 对象。
     *
     * @param json 待解析的 JSON 字符串
     * @return 解析后的 Map 对象，若 json 为空则返回 null
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> json2map(String json) {
        return StringUtils.isBlank(json) ? null : JsonUtil.fromJson(json, Map.class);
    }

    /**
     * 将 GroupInfoEntity 对象转换为 GroupInfoResponseVO 响应对象。
     *
     * @param e 待转换的 GroupInfoEntity 实体对象
     * @return 转换后的 GroupInfoResponseVO 响应对象
     */
    private GroupInfoResponseVO toVO(GroupInfoEntity e) {
        return GroupInfoResponseVO.builder()
                .paiId(e.getPaiId())
                .name(e.getName())
                .announcement(e.getAnnouncement())
                .remark(e.getRemark())
                .avatar(e.getAvatar())
                .ownerId(e.getOwnerId())
                .joinMode(e.getJoinMode())
                .maxMembers(e.getMaxMembers())
                .status(e.getStatus())
                .ext(json2map(e.getExt()))
                .createDate(e.getCreateDate())
                .updateDate(e.getUpdateDate())
                .build();
    }

}
